﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using App.Pay.WePay.XcxPay;
using Coldairarrow.Business;
using Coldairarrow.Entity;
using Coldairarrow.Entity.Backstage.TheRules;
using Coldairarrow.Entity.Backstage.UserData;
using Coldairarrow.Entity.BTB_StaffUsers;
using Coldairarrow.Entity.Goods;
using Coldairarrow.Entity.Pay;
using Coldairarrow.IBusiness.Pay;
using Coldairarrow.Util;
using Coldairarrow.Util.lib;
using EFCore.Sharding;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Serilog;
using ThoughtWorks.QRCode.Codec;
using WxPayAPI;

namespace Coldairarrow.Api.Controllers.Pay
{
  
    [Route("/Pay/[controller]/[action]")]
    [NoCheckJWT]
    public class WeChatH5PayController : BaseController
    {
        private IOrder_MasterBusiness _order_MasterBus { get; }
        private IOutbound_DetailsBusiness _outbound_DetailsBusiness { get; }
        private IWeChatParameterBusiness _weChatParameterBusiness { get; }
        public ILogger<WeChatPayController> _logger;
        private IDbAccessor _DB;

        public WeChatH5PayController(ILogger<WeChatPayController> logger, IDbAccessor db, IOrder_MasterBusiness order_MasterBus, IOutbound_DetailsBusiness outbound_DetailsBusiness, IWeChatParameterBusiness weChatParameterBusiness)
        {
            _outbound_DetailsBusiness = outbound_DetailsBusiness;
            _weChatParameterBusiness = weChatParameterBusiness;
            _order_MasterBus = order_MasterBus;
            _logger = logger;
            _DB = db;
        }
        #region 微信H5支付
        /// <summary>
        /// 微信H5支付
        /// </summary>
        /// <summary>
        /// 小程序下单
        /// </summary>
        /// <param name="input">openid</param>
        /// <returns></returns>
        [HttpPost]
        public object WxH5Pay([FromBody]WechatPay input)
        {
            #region 验证订单是否有效,并合计价格
            var data1 = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == input.oIds).ToList();

            if (data1.Count == 0)
            {
                throw new BusException("未查询到此订单请重新下单重试！");
            }
            else if (data1.Count > 0 && data1[0].PayState > 0)
            {
                throw new BusException("此订单已支付，请勿重新支付！");
            }

            Serilog.Log.Information("开启微信H5支付==========》");
            Serilog.Log.Information("WXH5ZF->input.oIds={0}", input.oIds);
            Serilog.Log.Information("WXH5ZF->input.openid={0}", input.openid);
            Serilog.Log.Information("WXH5ZF->input.detail={0}", input.detail);
            input.payPrice = data1[0].TotalPrice;

            Serilog.Log.Information("WXGZHZF->input.payPrice={0}", Convert.ToInt32(input.payPrice * 100));
            #endregion

            #region 统一下单
            if (data1.Count() > 0 && input.payPrice.HasValue && input.payPrice > 0)
            {
                try
                {
                    //支付回调通知地址
                    var notifyAddress = "https://api.leyi123.com/Pay/WeChatH5Pay/Wxh5NotifyUrl";
                    Serilog.Log.Information("WXH5ZF->回调地址={0}", notifyAddress);
                    WxPayData data = new WxPayData();
                    data.SetValue("body", "商品购买");

                    int payMoney = Convert.ToInt32(input.payPrice * 100);
                    //int payMoney = 1;

                    //可以将用户Id和订单Id同时封装在attach中
                    data.SetValue("attach", input.oIds);
                    Random rd = new Random();
                    //外部商户订单号
                    var payNum = DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next(0, 1000).ToString().PadLeft(3, '0');
                    data.SetValue("appid", WxPayGZHConfig.GetConfig().GetAppID());//公众帐号id
                    data.SetValue("out_trade_no", payNum);
                    data.SetValue("detail", input.detail);
                    data.SetValue("total_fee", payMoney);
                    data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
                    data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
                    data.SetValue("notify_url", notifyAddress);
                    //data.SetValue("goods_tag", "test");
                    data.SetValue("trade_type", "MWEB");

                    string secenInfo = "{\"h5_info\":{\"type\":\"Wap\",\"wap_url\":\"http://www.leyi123.com\",\"wap_name\":\"乐邑商城\"}";
                    data.SetValue("scene_info", secenInfo);

                    //data.SetValue("openid", input.openid);
                    //价格对比
                    List<Order_Master> aa = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == input.oIds && q.PayState != 1 && q.TotalPrice == Convert.ToDecimal(input.payPrice) && q.PayState == 0).ToList();
                    if (aa.Count <= 0)
                    {
                        throw new BusException("订单内部出现异常，请联系管理员", errorCode: -1);
                    }
                    aa[0].ExternalOrder = payNum;
                    _order_MasterBus.UpdateDataAsync(aa[0]);
                    WxPayData result = WxGZHPayApi.UnifiedOrder(data);//调用统一下单接口

                    var return_code = result.GetValue("return_code").ToString();
                    var return_msg = result.GetValue("return_msg").ToString();
                    if (return_code != "SUCCESS")
                    {
                        _logger.LogInformation("预下单失败：" + return_msg + "，请联系管理员");
                        throw new BusException("预下单失败：" + return_msg + "，请联系管理员", errorCode: -1);
                    }

                    var result_code = result.GetValue("result_code").ToString();
                    if (result_code != "SUCCESS")
                    {
                        _logger.LogInformation("预下单失败：" + return_msg+ "，请联系管理员");
                       throw new BusException("预下单失败：" + return_msg+ "，请联系管理员", errorCode: -1);
                    }

                    var trade_type = result.GetValue("trade_type").ToString();
                    var mweb_url = result.GetValue("mweb_url").ToString();

                    var timeStamp = ((DateTime.Now.Ticks - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).Ticks) / 10000).ToString();
                    
                    _logger.LogInformation(timeStamp + return_code + result_code + return_msg + trade_type + mweb_url + "预下单成功");
                    return (new { timeStamp, trade_type, mweb_url});
                }
                catch (Exception ex)
                {
                    return (new { Result = false, msg = "缺少参数" });
                }
            }
            else
            {
                return (new { Result = false, msg = "该订单已被支付" });
            }
            #endregion

        }

        /// <summary>
        /// 微信公众号支付回调通知
        ///</summary>
        ///<returns></returns>
        public async Task<ActionResult> Wxh5NotifyUrl()
        {
            _logger.LogInformation("H5支付开始回调");
            var k = HttpContext.Request.Body;
            using (var reader = new StreamReader(k))
            {

                var body = await reader.ReadToEndAsync();
                _logger.LogInformation("回调参数" + body);
                if (string.IsNullOrEmpty(body))
                {
                    //跳转到支付失败页面
                    return Content("<xml><return_code>FAIL</return_code><return_msg>回调参数为空</return_msg></xml>", "text/xml");
                }
                else
                {
                    var xmlDoc = XDocument.Parse(body);

                    _logger.LogInformation("订单号" + xmlDoc.Element("xml").Element("out_trade_no").ToString());
                    //微信订单号
                    var _transaction_id = xmlDoc.Element("xml").Element("transaction_id").Value;
                    //自定义订单号
                    var _out_trade_no = xmlDoc.Element("xml").Element("out_trade_no").Value;
                    //返回code码
                    var _return_code = xmlDoc.Element("xml").Element("return_code").Value;
                    //身份证
                    var _attach = xmlDoc.Element("xml").Element("attach").Value;
                    //交易结束时间
                    var _time_end = xmlDoc.Element("xml").Element("time_end").Value;
                    //支付金额
                    var _total_fee = xmlDoc.Element("xml").Element("total_fee").Value;

                    //检查支付结果中transaction_id是否存在
                    if (_transaction_id.IsNullOrEmpty())
                    {


                        //若transaction_id不存在，则立即返回结果给微信支付后台
                        XcxPayData res = new XcxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "支付结果中微信订单号不存在");
                        Serilog.Log.Information(this.GetType().ToString(), "+++++++++++++++++++++The Pay result is error : " + res.ToXml());

                        //跳转到支付成功页面
                        return Content("<xml><return_code>FAIL</return_code><return_msg>订单号不存在</return_msg></xml>", "text/xml");
                    }
                    else
                    {
                        //查询订单，判断订单真实性
                        if (!H5QueryOrder(_transaction_id))
                        {


                            //若订单查询失败，则立即返回结果给微信支付后台
                            XcxPayData res = new XcxPayData();
                            res.SetValue("return_code", "FAIL");
                            res.SetValue("return_msg", "订单查询失败");
                            Serilog.Log.Information(this.GetType().ToString(), "++++++++++++++++++++Order query failure : " + res.ToXml());

                            //跳转到支付失败页面
                            return Content("<xml><return_code>FAIL</return_code><return_msg>订单查询失败</return_msg></xml>", "text/xml");
                        }
                        //查询订单成功
                        else
                        {
                            List<Order_Master> aa = _DB.GetIQueryable<Order_Master>(true).Where(q => q.ExternalOrder == xmlDoc.Element("xml").Element("out_trade_no").Value).ToList();
                            _logger.LogInformation("Order_Master aa.Count = " + aa.Count);
                            if (aa.Count == 0)
                            {
                                int sCount = _DB.GetIQueryable<Order_Master>(true).Where(q => q.ExternalOrder == _transaction_id).Count();
                                if (sCount > 0)
                                {
                                    return Content("<xml><return_code>SUCCESS</return_code><return_msg>已支付成功OK</return_msg></xml>", "text/xml");

                                }
                                else
                                {
                                    //跳转到支付失败页面
                                    return Content("<xml><return_code>FAIL</return_code><return_msg>支付失败</return_msg></xml>", "text/xml");
                                }
                            }
                            else
                            {
                                XcxPayData res = new XcxPayData();
                                res.SetValue("return_code", "SUCCESS");
                                res.SetValue("return_msg", "OK");
                                _logger.LogInformation("Order query success : " + res.ToXml());
                                var returnCode = _return_code;
                                var transactionNo = _transaction_id;//微信订单号
                                var outTradeNo = _out_trade_no;//自定义订单号
                                var attach = _attach;//身份证
                                _logger.LogInformation("订单号" + attach);
                                var endTime = _time_end;//交易结束时间
                                var totalFee = _total_fee; ;//支付金额
                                aa[0].OrderState = 1;
                                aa[0].PayState = 3;
                                aa[0].ExternalOrder = _transaction_id;
                                _logger.LogInformation("更新订单数据开始===》");
                                _DB.Update<Order_Master>(aa[0]);
                                _logger.LogInformation("更新订单数据成功《===");
                                List<Outbound_Details> bb = _DB.GetIQueryable<Outbound_Details>(true).Where(q => q.OrderMater_Id == _attach).ToList();
                                _logger.LogInformation("Outbound_Details  bb.Count" + bb.Count);
                                bb[0].Bound_Flag = 2;

                                await _outbound_DetailsBusiness.UpdateDataAsync(bb[0]);
                                _logger.LogInformation("Outbound_Details  Update 成功");
                                WeChatParameter data = new WeChatParameter()
                                {
                                    Id = IdHelper.GetId(),
                                    out_trade_no = outTradeNo,
                                    _SumMoney = Convert.ToDecimal(_total_fee),
                                    _Orderid = _attach,
                                    transaction_id = _transaction_id,
                                    PayMode = 3,
                                    CreateTime = DateTime.Now
                                };
                                await _weChatParameterBusiness.AddDataAsync(data);
                                _logger.LogInformation("WeChatParameter  Add成功");
                                await stock(_attach);
                                _logger.LogInformation("+回调成功+");
                                var result = true;

                                #region//分销代码
                                //查询上级人员
                                var theUser = _DB.GetIQueryable<BTB_StaffUser>().Where(x => x.id.Equals(aa[0].CreatorId)).ToList();
                                if (theUser.Count > 0)
                                {
                                    var sjUser = _DB.GetIQueryable<BTB_StaffUser>().Where(x => x.User_YQCode.Equals(theUser[0].User_BYQCode)).ToList();
                                    if (sjUser.Count > 0)
                                    {
                                        //获取所有商品
                                        var gList = _DB.GetIQueryable<Order_Decimal>().Where(x => x.OrderMaster_Id.Equals(aa[0].Id)).ToList();
                                        int syNum = 0;

                                        //查询默认返利折扣
                                        int dsCount = 0;
                                        var dfList = _DB.GetIQueryable<BS_Rebate>().Where(x => x.GoodsId.Equals("****") && x.IsDefault).ToList();
                                        if (dfList.Count > 0)
                                        {
                                            dsCount = (int)dfList[0].ReturnDiscount;
                                        }
                                        List<BS_UserRebate> uList = new List<BS_UserRebate>();
                                        foreach (var item in gList)
                                        {
                                            //查询商品返利折扣
                                            var dgfList = _DB.GetIQueryable<BS_Rebate>().Where(x => x.GoodsId.Equals(item.Product_Id) && x.IsDefault).ToList();
                                            if (dgfList.Count > 0)
                                            {
                                                dsCount = (int)dgfList[0].ReturnDiscount;
                                            }

                                            if (dsCount > 0)
                                            {
                                                int rMoney = (int)(((decimal)item.SumProducts * dsCount) / 100);
                                                if (rMoney > 0)
                                                {
                                                    BS_UserRebate model = new BS_UserRebate();
                                                    model.Id = IdHelper.GetId();
                                                    model.Deleted = false;
                                                    model.CreatorId = theUser[0].id;
                                                    model.CreateTime = DateTime.Now;
                                                    model.SUserId = sjUser[0].id;
                                                    model.XFUserId = theUser[0].id;
                                                    model.OrderId = aa[0].Id;
                                                    model.GoodsId = item.Products_Id;
                                                    model.ReturnDiscount = dsCount;
                                                    model.OrderMoney = (decimal)item.SumProducts;
                                                    model.GoodsName = item.ProductNames;
                                                    model.GoodsItemName = item.ProductitemNames;
                                                    model.GoodsPrice = item.ProductPrice;
                                                    model.GoodsNum = item.Products_Num;
                                                    model.Note = theUser[0].NickName.Substring(0, 1) + "*购买" + item.ProductitemNames + "收益";
                                                    model.Type = 0;
                                                    model.ReturnMoney = rMoney;
                                                    syNum += rMoney;
                                                    uList.Add(model);
                                                }

                                                var upMList = _DB.GetIQueryable<BS_UserICPoint>().Where(x => x.UserId.Equals(sjUser[0].id)).ToList();
                                                if (upMList.Count > 0)
                                                {
                                                    upMList[0].Income += syNum;

                                                    await _DB.UpdateAsync(upMList[0]);
                                                    await _DB.InsertAsync(uList);
                                                }
                                                else
                                                {
                                                    BS_UserICPoint upModel = new BS_UserICPoint();
                                                    upModel.Id = IdHelper.GetId();
                                                    upModel.Deleted = false;
                                                    upModel.CreatorId = theUser[0].id;
                                                    upModel.CreateTime = DateTime.Now;
                                                    upModel.UserId = sjUser[0].id;
                                                    upModel.Income = syNum;
                                                    upModel.Point = 0;

                                                    await _DB.InsertAsync(upModel);
                                                    await _DB.InsertAsync(uList);
                                                }


                                            }

                                        }


                                    }
                                }

                                #endregion

                                Serilog.Log.Information(this.GetType().ToString(), "CompleteWePay:" + result);

                                //跳转微信支付成功页面
                                return Content("<xml><return_code>SUCCESS</return_code><return_msg>支付成功OK</return_msg></xml>", "text/xml");
                            }
                        }
                    }
                }
              
            }
        }

        [HttpPost]
        public bool QueryTheOrder([FromBody] IdInputDTO input)
        {
            List<Order_Master> orderList = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == input.id).ToList();
            if (orderList.Count == 0)
            {
                throw new BusException("查询订单失败！");
            }
            else
            {
                if (orderList[0].OrderState == 0 || orderList[0].PayState == 0)
                {
                    return false;
                }

                var transaction_id = orderList[0].ExternalOrder;
                List<WeChatParameter> pareList = _DB.GetIQueryable<WeChatParameter>(true).Where(q => q.transaction_id == transaction_id).ToList();
                if (pareList.Count == 0)
                {
                    return false;
                }

                XcxPayData req = new XcxPayData();
                req.SetValue("transaction_id", transaction_id);
                XcxPayData res = GzhPayApi.OrderQuery(req);
                if (res.GetValue("return_code").ToString() == "SUCCESS" && res.GetValue("result_code").ToString() == "SUCCESS")
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

        }

        /// <summary>
        /// 查询订单
        /// </summary>
        /// <param name="transaction_id">微信交易订单号</param>
        /// <returns></returns>
        private bool H5QueryOrder(string transaction_id)
        {
            XcxPayData req = new XcxPayData();
            req.SetValue("transaction_id", transaction_id);
            XcxPayData res = GzhPayApi.OrderQuery(req);
            if (res.GetValue("return_code").ToString() == "SUCCESS" && res.GetValue("result_code").ToString() == "SUCCESS")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion

        public async Task stock(string id)
        {
            _logger.LogInformation("库存修改:" + id);
            var data = _DB.GetIQueryable<Order_Decimal>(true).Where(q => q.OrderMaster_Id == id).ToList();
            _logger.LogInformation("商品数据" + data.Count);
            foreach (var item in data)
            {
                var aa = item.Product_Id;
                _logger.LogInformation("商品+++++++++++++id" + aa);
                var Product = _DB.GetIQueryable<BTB_Goods>(true).FirstOrDefault(q => q.ID == item.Product_Id);
                _logger.LogInformation("回调成功+++++++++++++++++++++++" + Product);
                var Products = _DB.GetIQueryable<BTB_GoodsSpecificationsItem>(true).FirstOrDefault(q => q.GoodsSpecificationsItemID == item.Products_Id);
                _logger.LogInformation("回调成功+++++++++++++++++++++++" + Products);
                Product.SaleCount += (int)item.Products_Num;
                _logger.LogInformation("回调增加销量成功+++++++++++++++++++++++" + Product.SaleCount);
                if (!Products.IsNullOrEmpty())
                {
                    Products.Inventory = (int)Products?.Inventory - (int)item?.Products_Num;
                    _logger.LogInformation("回调修改库存成功+++++++++++++++++++++++" + Products.Inventory);
                    await _DB.UpdateAsync<BTB_GoodsSpecificationsItem>(Products);
                }
                await _DB.UpdateAsync<BTB_Goods>(Product);
            }
        }

    }
}
